const robot = require('robotjs');
const fs = require('fs');
const path = require('path');
const common = require('./common');
const axios = require('axios');
const { link } = require('original-fs');
const { logger } = require('./common');
const { time } = require('console');
let task = {
    isRunningRetryFailTrades: false,
    failTrades: [],
    douyinIndex: 'https://www.douyin.com/'
};

task.accountLogin = async function () {
    await task.openPage(true, task.douyinIndex, 10000,).then(async page => {
        await page.waitForSelector('div.web-login-scan-code__content', { timeout: 20000 }).then(async result => {
            let checkLoginTimes = 0;

            for (let i = 0; i > -1; i++) {
                let renderDataNode = await page.$('#RENDER_DATA').catch(error => { });
                let saveButton = await page.$('div.trust-login-dialog-button-confirm');

                if (saveButton) {
                    await saveButton.evaluate(b => b.click());
                    await common.logger.warn('保存按钮');
                    await common.sleep(5000);
                    let guideMask = await page.waitForSelector('#douyin-web-recommend-guide-mask', { timeout: 10000 }).catch(error => common.logger.error(error.message + '\r\n' + error.stack));

                    if (guideMask) {
                        common.logger.warn('引导存在');
                        robot.keyTap('down');
                        await common.sleep(5000);
                    }
                }

                if (renderDataNode) {
                    let jsonEncryTxt = await page.evaluate(node => node.innerText, renderDataNode).catch(error => { common.logger.error(error.message + '\r\n' + error.stack) });

                    try {
                        let jsonTxt = decodeURIComponent(jsonEncryTxt);
                        let douyin = jsonTxt ? JSON.parse(jsonTxt) : undefined;

                        if (douyin && douyin.app.user.isLogin) {
                            checkLoginTimes++;
                            await common.logger.warn('checkLoginTimes --> ' + checkLoginTimes);

                            if (checkLoginTimes > 2) {
                                let cookies = await page.cookies();
                                let account = { nickName: douyin.app.user.info.nickname, uniqueId: douyin.app.user.info.uniqueId, cookies: JSON.stringify(cookies) };
                                task.reportAccount(account);
                                await page.close();
                                break;
                            }
                        }
                    } catch (error) {
                        common.logger.error(error.message + '\r\n' + error.stack);
                    }

                    await common.sleep(600);
                } else {
                    await common.sleep(600);
                }
            }
        }).catch(error => { common.logger.error(error.message + '\r\n' + error.stack); });
    }, reason => {
        common.logger.warn(reason);
    }).catch(error => common.logger.error(error.message + '\r\n' + error.stack));
}

task.openPage = async function (isForceBrowser, url, timeout, proxy, cookies) {
    let promise = new Promise(async (resolve, reject) => {
        try {
            let browser = await common.getBrowser(isForceBrowser, proxy, cookies);
            let pages = await browser.pages();

            for (let i = 0; i < pages.length; i++) {
                let _page = pages[i];

                if (_page.url() != 'about:blank') {
                    await _page.close();
                } else {
                    common.logger.warn(_page.url())
                }
            }

            let page = await browser.newPage();

            if (cookies) {
                for (let index = 0; index < cookies.length; index++) {
                    let cookie = cookies[index];
                    await page.setCookie(cookie);
                }
            }

            await page.goto(url, { timeout: timeout }).catch(async error => {
                common.logger.error(error.message + '\r\n' + error.stack);
                await page.reload({ timeout: timeout }).catch(error => common.logger.error(error.message + '\r\n' + error.stack));
            });
            resolve(page);
        } catch (error) {
            common.logger.error(error.message + '\r\n' + error.stack);
            reject(error);
        }
    });

    return promise;
}

task.reportAccount = async function (account) {
    axios.post(common.apiUrl + '/api/account/report', account, { headers: { username: common.getUserName(), code: common.getCode() } }).then(res => {
        common.logger.warn(JSON.stringify(res.data));

        if (res && res.data) {
            if (res.data.code == 1) {
                reportStatus = 1;
            } else {
                common.logger.warn('上报账号失败 --> ' + JSON.stringify(account));
            }
        }
    }).catch(function (error) {
        common.logger.warn('上报账号失败 --> ' + JSON.stringify(account));
        common.logger.error(error.message + '\r\n' + error.stack);
    });
}

task.downloadImage = async function (imageUrl) {
    let fileArr = imageUrl.split('/');
    let fileName = fileArr[fileArr.length - 1];
    let now = new Date();
    let year = now.getFullYear();
    let month = common.padNumber(now.getMonth() + 1);
    let day = common.padNumber(now.getDate());
    let imagePath = path.join(process.cwd(), 'images', `${year}-${month}-${day}`, fileName);
    fs.mkdirSync(path.join(process.cwd(), 'images', `${year}-${month}-${day}`), { recursive: true });

    let promise = new Promise(async (resolve, reject) => {
        if (fs.existsSync(imagePath)) {
            resolve(imagePath);
        } else {
            await axios({
                url: imageUrl,
                method: 'GET',
                responseType: 'stream'
            }).then(async res => {
                let writer = fs.createWriteStream(imagePath);
                res.data.pipe(writer);
                console.log('downloadExcel over')
                writer.on('finish', function () {
                    resolve(imagePath);
                });
                writer.on('error', function () {
                    reject('下载失败');
                });
            }).catch(error => reject(error));
        }
    });

    return promise;
}

task.getProxyIp = async function () {
    let proxyApi = common.getConfig('proxyApi', '');
    let promise = new Promise(async (resolve, reject) => {
        await axios({
            url: proxyApi,
            method: 'GET'
        }).then(async res => {
            common.logger.warn(JSON.stringify(res.data));

            if (res.data.code == 0) {
                if (res.data.data.length > 0) {
                    resolve(res.data.data[0]);
                } else {
                    reject("data's length is zero");
                }
            } else {
                reject('request fail');
            }
        }).catch(error => {
            common.logger.error(error.message + '\r\n' + error.stack);
            reject('request error');
        });
    });

    return promise;
}

task.getComment = async function () {
    let url = common.apiUrl + '/api/comment/get';
    let data = null;

    await axios({
        url: url,
        method: 'post',
        data: { clientName: common.getConfig('clientName', '') },
        headers: { username: common.getUserName(), code: common.getCode() }
    }).then(async res => {
        if (res.data.code == 1) {
            if (res.data.data) {
                common.logger.warn(JSON.stringify({
                    comment: res.data.data.comment,
                    account: {
                        uniqueId: res.data.data.account.uniqueId,
                        nickName: res.data.data.account.nickName
                    },
                    link: res.data.links
                }))
                data = res.data.data;
            } else {
                common.logger.warn("data is null");
            }
        } else {
            common.logger.warn('request fail');
        }
    }).catch(async error => {
        common.logger.error(error.message + '\r\n' + error.stack);
    });

    return data;
}

task.reportComment = async function (id) {
    let url = common.apiUrl + '/api/comment/report';
    let promise = new Promise(async (resolve, reject) => {
        await axios({
            url: url,
            method: 'post',
            data: { id: id },
            headers: { username: common.getUserName(), code: common.getCode() }
        }).then(async res => {
            common.logger.warn(res.data);

            if (res.data.code == 1) {

            } else {
                reject('request fail');
            }
        }).catch(error => {
            common.logger.error(error.message + '\r\n' + error.stack);
            reject('request error');
        });
    });

    return promise;
}

task.releaseComment = async function (id) {
    let url = common.apiUrl + '/api/comment/release';
    let promise = new Promise(async (resolve, reject) => {
        await axios({
            url: url,
            method: 'post',
            data: { id: id },
            headers: { username: common.getUserName(), code: common.getCode() }
        }).then(async res => {
            common.logger.warn(res.data);

            if (res.data.code == 1) {

            } else {
                reject('request fail');
            }
        }).catch(error => {
            common.logger.error(error.message + '\r\n' + error.stack);
            reject('request error');
        });
    });

    return promise;
}

task.test = async function () {
    for (let i = 0; i > -1; i++) {
        let requestInterval = 10000;

        try {
            requestInterval = parseInt(common.getConfig('requestInterval', '10000'));
            let data = await task.getComment();

            if (data) {
                let isSuccess = false;

                try {
                    let imagePath = '';

                    if (data.comment.contentType == 2) {
                        imagePath = await task.downloadImage(data.comment.content);
                    }

                    // let proxy = await task.getProxyIp();
                    let proxy = true;

                    if (proxy) {
                        let cookies = JSON.parse(data.account.cookies);
                        let proxyInfo = proxy.ip + ':' + proxy.port;
                        common.logger.warn(proxyInfo);
                        // await task.openPage(true, data.link, 15000, proxyInfo, cookies).then(async page => {
                            await task.openPage(true, data.link, 10000, '', cookies).then(async page => {
                            await common.sleep(3000);
                            for (let j = 0; j < 5; j++) {
                                if (page.url().indexOf('/video/') > -1) {
                                    let urlArr = page.url().split('/');
                                    let newUrl = 'https://www.douyin.com/discover?modal_id=' + urlArr[urlArr.length - 1].replace('?previous_page=web_code_link', '');
                                    common.logger.warn('new url is ' + newUrl);
                                    await page.goto(newUrl, { timeout: 15000 }).catch(error => common.logger.error(error.message + '\r\n' + error.stack));
                                    break;
                                } else {
                                    await common.sleep(1200);
                                }
                            }

                            await page.waitForSelector('div.account-name', { timeout: 20000 }).catch(error => common.logger.error(error.message + '\r\n' + error.stack));
                            await common.sleep(common.randomNum(5, 10) * 1000);
                            let isLike = common.randomNum(1, 100) < 50;//点赞
                            let isCollect = common.randomNum(1, 100) < 10;//收藏

                            if (isLike) {
                                let noDiggedNodes = await page.$x('//div[@data-e2e-state="video-player-no-digged"]');

                                if (noDiggedNodes.length > 1) {
                                    // await noDiggedNodes[0].click();
                                    await noDiggedNodes[0].evaluate(b => b.click());
                                    await common.sleep(common.randomNum(1, 3) * 1000);
                                }
                            }

                            if (isCollect) {
                                let noCollectNodes = await page.$x('//div[@data-e2e-state="video-player-no-collect"]');

                                if (noCollectNodes.length > 1) {
                                    // await noCollectNodes[0].click();
                                    await noCollectNodes[0].evaluate(b => b.click());
                                    await common.sleep(common.randomNum(1, 3) * 1000);
                                }
                            }

                            let commentNodes = await page.$x('//div[@data-e2e="feed-comment-icon"]');

                            if (commentNodes.length > 1) {
                                // await commentNodes[0].click();
                                await commentNodes[0].evaluate(b => b.click());
                                await common.sleep(common.randomNum(3, 5) * 1000);

                                if (data.comment.contentType == 1) {
                                    // await common.clickNodesByXPath('div[@data-contents="true"]', page, 3000);//点击输入框
                                    await common.clickNodesByXPath('//span[text()="留下你的精彩评论吧"]', page, 3000);//点击输入框
                                    await page.type('br[data-text="true"]', data.comment.content.substr(0, 1), { delay: 102 }).catch(error => common.logger.error(error.message + '\r\n' + error.stack));
                                    await common.sleep(1500, 1600);
                                    await page.type('span[data-text="true"]', data.comment.content.substring(1), { delay: 102 }).catch(error => common.logger.error(error.message + '\r\n' + error.stack));
                                    await common.sleep(1500, 1600);
                                } else {
                                    let [fileChooser] = await Promise.all([
                                        page?.waitForFileChooser(),
                                        await common.clickNodesByXPath('//div[contains(@class,"commentInput-right-ct")]/div/span[1]', page, 1000, 1500)
                                    ]);

                                    await fileChooser?.accept([imagePath]);
                                    await common.sleep(1200);
                                }

                                await common.clickNodesByXPath('//div[contains(@class,"commentInput-right-ct")]/div/span[4]', page, 3000);
                                isSuccess = true;
                            }
                        }).catch(error => common.logger.error(error.message + '\r\n' + error.stack));
                    }
                } catch (error) {
                    common.logger.error(error.message + '\r\n' + error.stack)
                } finally {
                    if (data && data.comment) {
                        if (isSuccess) {
                            await task.reportComment(data.comment.id);
                        } else {
                            await task.releaseComment(data.comment.id);
                        }
                    }
                }
            }
        } catch (error) {
            common.logger.error(error.message + '\r\n' + error.stack);
        }

        await common.sleep(requestInterval * 1000);
    }
}

module.exports = task;